/*
 * Copyright © 2025 秋辞未寒 (545073804@qq.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.gitee.colordreams.mapstruct.convert.mapper;

import org.mapstruct.MappingTarget;

import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * SourceTargetMapper接口
 * <pre>提供源(S)对象和目标(T)对象之间的转换功能</pre>
 * <pre>Provide the conversion function between the Source(S) object and the Target(T) object.</pre>
 *
 * @param <S> 源类型 Source Type
 * @param <T> 目标类型 Target Type
 * @author 秋辞未寒
 */
public interface SourceTargetMapper<S, T> extends MapperAware {

    /**
     * 将源对象转换为目标对象
     *
     * @param source 源对象
     * @return 目标对象
     */
    T toTarget(S source);

    /**
     * 将源对象转换为目标对象
     *
     * @return 目标对象转换函数
     */
    default Function<S, T> toTargetFunction() {
        return this::toTarget;
    }

    /**
     * 将源对象转换为目标对象
     *
     * @param source 源对象
     * @param after  转换后操作
     * @return 目标对象
     */
    default T toTarget(S source, Consumer<T> after) {
        T target = toTarget(source);
        after.accept(target);
        return target;
    }

    /**
     * 将源对象转换为目标对象
     *
     * @param after 转换后操作
     * @return 目标对象转换函数
     */
    default Function<S, T> toTargetFunction(Consumer<T> after) {
        return source -> toTarget(source, after);
    }

    /**
     * 将源对象转换为目标对象
     *
     * @param source 源对象
     * @param after  转换后操作
     * @return 目标对象
     */
    default T toTarget(S source, BiConsumer<S, T> after) {
        T target = toTarget(source);
        after.accept(source, target);
        return target;
    }

    /**
     * 将源对象转换为目标对象
     *
     * @param after 转换后操作
     * @return 目标对象转换函数
     */
    default Function<S, T> toTargetFunction(BiConsumer<S, T> after) {
        return source -> toTarget(source, after);
    }

    /**
     * 将源对象转换为目标对象
     *
     * @param source 源对象
     * @param target 目标对象
     */
    void toTarget(S source, @MappingTarget T target);

    /**
     * 将源对象转换为目标对象
     *
     * @param target 目标对象
     * @return 目标对象转换函数
     */
    default Function<S, T> toTargetFunction(T target) {
        return source -> {
            toTarget(source, target);
            return target;
        };
    }

    /**
     * 将源对象转换为目标对象
     *
     * @param source 源对象
     * @param target 目标对象
     * @param after  转换后操作
     */
    default void toTarget(S source, T target, Consumer<T> after) {
        toTarget(source, target);
        after.accept(target);
    }

    /**
     * 将源对象转换为目标对象
     *
     * @param target 目标对象
     * @param after  转换后操作
     * @return 目标对象转换函数
     */
    default Function<S, T> toTargetFunction(T target, Consumer<T> after) {
        return source -> {
            toTarget(source, target, after);
            return target;
        };
    }

    /**
     * 将源对象转换为目标对象
     *
     * @param source 源对象
     * @param target 目标对象
     * @param after  转换后操作
     */
    default void toTarget(S source, T target, BiConsumer<S, T> after) {
        toTarget(source, target);
        after.accept(source, target);
    }

    /**
     * 将源对象转换为目标对象
     *
     * @param target 目标对象
     * @param after  转换后操作
     * @return 目标对象转换函数
     */
    default Function<S, T> toTargetFunction(T target, BiConsumer<S, T> after) {
        return source -> {
            toTarget(source, target, after);
            return target;
        };
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param sourceList 源对象列表
     * @return 目标对象列表
     */
    default List<T> toTargetList(List<S> sourceList) {
        return sourceList.stream()
                .map(this::toTarget)
                .collect(Collectors.toList());
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @return 目标对象转换函数
     */
    default Function<List<S>, List<T>> toTargetListFunction() {
        return this::toTargetList;
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param sourceList 源对象列表
     * @param eachAfter  每一个元素转换后操作
     * @return 目标对象列表
     */
    default List<T> toTargetList(List<S> sourceList, Consumer<T> eachAfter) {
        if (eachAfter == null) {
            return toTargetList(sourceList);
        }
        return sourceList.stream()
                .map(source -> toTarget(source, eachAfter))
                .collect(Collectors.toList());
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param eachAfter 每一个元素转换后操作
     * @return 目标对象转换函数
     */
    default Function<List<S>, List<T>> toTargetListFunction(Consumer<T> eachAfter) {
        return sourceList -> toTargetList(sourceList, eachAfter);
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param sourceList 源对象列表
     * @param eachAfter  每一个元素转换后操作
     * @return 目标对象列表
     */
    default List<T> toTargetList(List<S> sourceList, BiConsumer<S, T> eachAfter) {
        if (eachAfter == null) {
            return toTargetList(sourceList);
        }
        return sourceList.stream()
                .map(source -> toTarget(source, eachAfter))
                .collect(Collectors.toList());
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param eachAfter 每一个元素转换后操作
     * @return 目标对象转换函数
     */
    default Function<List<S>, List<T>> toTargetListFunction(BiConsumer<S, T> eachAfter) {
        return sourceList -> toTargetList(sourceList, eachAfter);
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param sourceList 源对象列表
     * @param listAfter  列表转换后操作
     * @return 目标对象列表
     */
    default List<T> toTargetListAll(List<S> sourceList, Consumer<List<T>> listAfter) {
        List<T> targetList = toTargetList(sourceList);
        if (listAfter != null && targetList != null) {
            listAfter.accept(targetList);
        }
        return targetList;
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param listAfter 列表转换后操作
     * @return 目标对象转换函数
     */
    default Function<List<S>, List<T>> toTargetListAllFunction(Consumer<List<T>> listAfter) {
        return sourceList -> toTargetListAll(sourceList, listAfter);
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param sourceList 源对象列表
     * @param listAfter  列表转换后操作
     * @return 目标对象列表
     */
    default List<T> toTargetListAll(List<S> sourceList, BiConsumer<List<S>, List<T>> listAfter) {
        List<T> targetList = toTargetList(sourceList);
        if (listAfter != null && targetList != null) {
            listAfter.accept(sourceList, targetList);
        }
        return targetList;
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param listAfter 列表转换后操作
     * @return 目标对象转换函数
     */
    default Function<List<S>, List<T>> toTargetListAllFunction(BiConsumer<List<S>, List<T>> listAfter) {
        return sourceList -> toTargetListAll(sourceList, listAfter);
    }

    /**
     * 将目标对象转换成源对象
     *
     * @param target 目标对象
     * @return 源对象
     */
    S toSource(T target);


    /**
     * 将目标对象转换成源对象
     *
     * @return 源对象转换函数
     */
    default Function<T, S> toSourceFunction() {
        return this::toSource;
    }

    /**
     * 将目标对象转换成源对象
     *
     * @param target 源对象
     * @param after  转换后操作
     * @return 源对象
     */
    default S toSource(T target, Consumer<S> after) {
        S source = toSource(target);
        after.accept(source);
        return source;
    }

    /**
     * 将目标对象转换成源对象
     *
     * @param after 转换后操作
     * @return 源对象转换函数
     */
    default Function<T, S> toSourceFunction(Consumer<S> after) {
        return target -> toSource(target, after);
    }

    /**
     * 将目标对象转换成源对象
     *
     * @param target 源对象
     * @param after  转换后操作
     * @return 源对象
     */
    default S toSource(T target, BiConsumer<S, T> after) {
        S source = toSource(target);
        after.accept(source, target);
        return source;
    }

    /**
     * 将目标对象转换成源对象
     *
     * @param after 转换后操作
     * @return 源对象转换函数
     */
    default Function<T, S> toSourceFunction(BiConsumer<S, T> after) {
        return target -> toSource(target, after);
    }

    /**
     * 将目标对象转换成源对象
     *
     * @param target 目标对象
     * @param source 源对象
     */
    void toSource(T target, @MappingTarget S source);

    /**
     * 将目标对象转换成源对象
     *
     * @param source 源对象
     * @return 源对象转换函数
     */
    default Function<T, S> toSourceFunction(S source) {
        return target -> {
            toSource(target, source);
            return source;
        };
    }

    /**
     * 将目标对象转换成源对象
     *
     * @param target 目标对象
     * @param source 源对象
     * @param after  转换后操作
     */
    default void toSource(T target, S source, Consumer<S> after) {
        toSource(target, source);
        after.accept(source);
    }

    /**
     * 将目标对象转换成源对象
     *
     * @param source 源对象
     * @param after  转换后操作
     * @return 源对象转换函数
     */
    default Function<T, S> toSourceFunction(S source, Consumer<S> after) {
        return target -> {
            toSource(target, source, after);
            return source;
        };
    }

    /**
     * 将目标对象转换成源对象
     *
     * @param target 目标对象
     * @param source 源对象
     * @param after  转换后操作
     */
    default void toSource(T target, S source, BiConsumer<S, T> after) {
        toSource(target, source);
        after.accept(source, target);
    }

    /**
     * 将目标对象转换成源对象
     *
     * @param source 源对象
     * @param after  转换后操作
     * @return 源对象转换函数
     */
    default Function<T, S> toSourceFunction(S source, BiConsumer<S, T> after) {
        return target -> {
            toSource(target, source, after);
            return source;
        };
    }

    /**
     * 将目标对象列表转换成源对象列表
     *
     * @param targetList 目标对象列表
     * @return 源对象列表
     */
    default List<S> toSourceList(List<T> targetList) {
        return targetList.stream()
                .map(this::toSource)
                .collect(Collectors.toList());
    }

    /**
     * 将目标对象列表转换成源对象列表
     *
     * @return 源对象转换函数
     */
    default Function<List<T>, List<S>> toSourceListFunction() {
        return this::toSourceList;
    }

    /**
     * 将目标对象列表转换成源对象列表
     *
     * @param targetList 目标对象列表
     * @param eachAfter  每一个元素转换后操作
     * @return 源对象列表
     */
    default List<S> toSourceList(List<T> targetList, Consumer<S> eachAfter) {
        if (eachAfter == null) {
            return toSourceList(targetList);
        }
        return targetList.stream()
                .map(target -> toSource(target, eachAfter))
                .collect(Collectors.toList());
    }

    /**
     * 将目标对象列表转换成源对象列表
     *
     * @param eachAfter 每一个元素转换后操作
     * @return 源对象转换函数
     */
    default Function<List<T>, List<S>> toSourceListFunction(Consumer<S> eachAfter) {
        return targetList -> toSourceList(targetList, eachAfter);
    }

    /**
     * 将目标对象列表转换成源对象列表
     *
     * @param targetList 目标对象列表
     * @param eachAfter  每一个元素转换后操作
     * @return 源对象列表
     */
    default List<S> toSourceList(List<T> targetList, BiConsumer<S, T> eachAfter) {
        if (eachAfter == null) {
            return toSourceList(targetList);
        }
        return targetList.stream()
                .map(target -> toSource(target, eachAfter))
                .collect(Collectors.toList());
    }

    /**
     * 将目标对象列表转换成源对象列表
     *
     * @param eachAfter 每一个元素转换后操作
     * @return 源对象转换函数
     */
    default Function<List<T>, List<S>> toSourceListFunction(BiConsumer<S, T> eachAfter) {
        return targetList -> toSourceList(targetList, eachAfter);
    }

    /**
     * 将目标对象列表转换成源对象列表
     *
     * @param targetList 目标对象列表
     * @param listAfter  列表转换后操作
     * @return 源对象列表
     */
    default List<S> toSourceListAll(List<T> targetList, Consumer<List<S>> listAfter) {
        List<S> sourceList = toSourceList(targetList);
        if (listAfter != null && sourceList != null) {
            listAfter.accept(sourceList);
        }
        return sourceList;
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param listAfter 列表转换后操作
     * @return 源对象转换函数
     */
    default Function<List<T>, List<S>> toSourceListAllFunction(Consumer<List<S>> listAfter) {
        return targetList -> toSourceListAll(targetList, listAfter);
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param targetList 目标对象列表
     * @param listAfter  列表转换后操作
     * @return 源对象列表
     */
    default List<S> toSourceListAll(List<T> targetList, BiConsumer<List<S>, List<T>> listAfter) {
        List<S> sourceList = toSourceList(targetList);
        if (listAfter != null && sourceList != null) {
            listAfter.accept(sourceList, targetList);
        }
        return sourceList;
    }

    /**
     * 将源对象列表转换为目标对象列表
     *
     * @param listAfter 列表转换后操作
     * @return 目标对象转换函数
     */
    default Function<List<T>, List<S>> toSourceListAllFunction(BiConsumer<List<S>, List<T>> listAfter) {
        return targetList -> toSourceListAll(targetList, listAfter);
    }

}
